#include "YUVItem.h"
#include "OpenglRender.h"
#include <QOpenGLFramebufferObject>
#include <QQuickWindow>

//************TItemRender************//
class TItemRender : public QQuickFramebufferObject::Renderer
{    
public:
    TItemRender();

    void render() override;
    QOpenGLFramebufferObject *createFramebufferObject(const QSize &size) override;
    void synchronize(QQuickFramebufferObject *) override;
    void updateTextureData(const YUVData &data);
private:
    OpenglRender m_render;
    QQuickWindow *m_window = nullptr;

    int m_videoWidth;
    int m_videoHeight;
};

TItemRender::TItemRender()
{
    m_render.init();    
}

void TItemRender::render()
{
    m_render.paint();
    m_window->resetOpenGLState();
}

void TItemRender::updateTextureData(const YUVData &data) {
    m_render.updateTextureData(data);
}

QOpenGLFramebufferObject *TItemRender::createFramebufferObject(const QSize &size)
{
    QOpenGLFramebufferObjectFormat format;
    format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
    format.setSamples(4);
    m_render.resize(size.width(), size.height());
    return new QOpenGLFramebufferObject(size, format);
}

void TItemRender::synchronize(QQuickFramebufferObject *item)
{
    YUVItem *pItem = qobject_cast<YUVItem *>(item);
    if (pItem)
    {
        if (!m_window)
        {
            m_window = pItem->window();
        }
        if (m_videoWidth != pItem->videoWidth() || m_videoHeight != pItem->videoHeght()) {
            m_videoWidth = pItem->videoWidth();
            m_videoHeight = pItem->videoHeght();
            m_render.updateTextureInfo(pItem->videoWidth(), pItem->videoHeght());
        }
        m_render.updateTextureData(pItem->getFrame());
    }
}

//************YUVItem************//
YUVItem::YUVItem(QQuickItem *parent) : QQuickFramebufferObject (parent)
{    
}

void YUVItem::OnFrameAvailable(const YUVData& frame) {
    m_frame = frame;
    update();
}

const YUVData& YUVItem::getFrame() {
    return m_frame;
}

QQuickFramebufferObject::Renderer* YUVItem::createRenderer() const
{
    TItemRender* renderer = new TItemRender;
    QObject::connect(&m_yuvLoader, &YUVLoader::newFrameAvailable, this, &YUVItem::OnFrameAvailable);
    return renderer;
}
